package com.yc.mysql.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

public class MBHelper {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            // mybatis 框架配置文件路径
            String resource = "mybatis.xml";
            // 读入配置
            InputStream inputStream = Resources.getResourceAsStream(resource);
            // 构建会话工厂
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (Exception e) {
            throw new RuntimeException("MyBatis初始化失败!", e);
        }
    }

    /**
     * 返回指定自动提交方式的会话
     */
    public static SqlSession openSession(boolean autoCommit){
        return sqlSessionFactory.openSession(autoCommit);
    }

    /**
     * 返回自动提交的会话
     */
    public static SqlSession openSession(){
        return openSession(true);
    }

    /**
     * 以事务控制方式执行业务的模板方法, 基于 SqlSession
     * @param executor 执行业务方法的接口对象( 函数接口 )
     */
    public static Object exec(ExecutorBySqlSession executor){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try{
           Object ret = executor.execute(sqlSession);
           // 提交
           sqlSession.commit();
           return ret;
        } catch (RuntimeException e){
            // 回滚
            sqlSession.rollback();
            throw e;
        } finally {
            // 关闭会话
            sqlSession.close();
        }
    }

    /**
     * 同上, 但不返回结果
     */
    public static void call(ExecutorBySqlSession executor){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try{
            executor.execute(sqlSession);
            // 提交
            sqlSession.commit();
        } catch (RuntimeException e){
            // 回滚
            sqlSession.rollback();
            throw e;
        } finally {
            // 关闭会话
            sqlSession.close();
        }
    }

    /**
     * 以事务控制方式执行业务的模板方法, 基于 Mapper
     * @param executor 执行业务方法的接口对象( 函数接口 )
     */
    public static <T> Object exec(Class<T> cls, ExecutorByMapper<T> executor){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try{
            T mapper = sqlSession.getMapper(cls);
            Object ret = executor.execute(mapper);
            // 提交
            sqlSession.commit();
            return ret;
        } catch (RuntimeException e){
            // 回滚
            sqlSession.rollback();
            throw e;
        } finally {
            // 关闭会话
            sqlSession.close();
        }
    }

    /**
     * 同上, 但不返回结果
     */
    public static <T> void call(Class<T> cls, ExecutorByMapper<T> executor){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try{
            T mapper = sqlSession.getMapper(cls);
            executor.execute(mapper);
            // 提交
            sqlSession.commit();
        } catch (RuntimeException e){
            // 回滚
            sqlSession.rollback();
            throw e;
        } finally {
            // 关闭会话
            sqlSession.close();
        }
    }

    /**
     * 执行业务方法的接口
     */
    public static interface ExecutorBySqlSession{
        Object execute(SqlSession sqlSession);
    }

    public static interface ExecutorByMapper<T>{
        Object execute(T mapper);
    }

}
